chore(deps): Bump @langchain/core 1.1.48 + @langchain/google-* 2.1.31, with Anthropic tool-input compat fix#232
Merged
Conversation
…o 2.1.31
Routine maintenance bump of the Google/LangChain stack:
- @langchain/core 1.1.44 -> 1.1.48
- @langchain/google-common / google-gauth / google-genai / google-vertexai 2.1.28 -> 2.1.31
These must move together: google-common 2.1.31 imports `v4` from
`@langchain/core/utils/uuid` (reverting 2.1.28's standalone-`uuid` import),
which is the same path that crashed in LibreChat#13003. core 1.1.48 fixes the
Rolldown CJS emit so that export resolves to a callable function again
(verified: `require('@langchain/core/utils/uuid').v4()` returns a UUID), so the
crash does not recur. Bumping google-common alone (core pinned at 1.1.44) would
reintroduce it.
Build (rollup + tsc) passes. Does not address the Gemini union-type schema
throw (langchain-ai/langchainjs#9691, still open) — that is handled downstream
in LibreChat.
danny-avila
added a commit
to danny-avila/LibreChat
that referenced
this pull request
Jun 9, 2026
The union flatten alone wasn't enough — real GitHub MCP tools on Gemini also 400 with `Invalid value ... (TYPE_STRING), true`, because Gemini's function-calling Schema (https://ai.google.dev/api/caching#Schema) accepts only a restricted JSON Schema subset, and `enum` is `Type.STRING`-only. Rename `flattenJsonSchemaUnions` → `sanitizeGeminiSchema` and broaden it (one pass, Gemini-gated) to cover the documented subset: - Keep only string `enum` values; drop the keyword for non-string types (fixes the reported boolean-enum 400, incl. boolean `const` normalized to `enum: [true]`). - `const` → single-value string enum, or drop if non-string. - Merge `allOf` intersections; fold `exclusiveMinimum`/`exclusiveMaximum` into `minimum`/`maximum`. - Strip unsupported keywords: `additionalProperties`, `default`, `$schema`, `$id`. - (Existing) collapse `anyOf`/`oneOf`, multi-entry `type` arrays, nullable. Grounded in Google's Schema docs rather than reverse-engineered from 400s. Verified end-to-end against the real `@langchain/google-common` converter. Complements danny-avila/agents#232 (langchain bump), which defers schema flattening to LibreChat.
7 tasks
…egation
@langchain/core >= 1.1.46 changed streaming content-block aggregation ("keep
different block types separate" + "v1 message casting"). For Anthropic tool
calls it now keeps the input_json_delta as a separate content block, v1-casts it
to a `text` block carrying `input` but no `text`, and leaves the sibling
tool_use block with an empty inline input. Re-serializing such a message threw
"Unsupported message content format" in _formatContent.
Align _formatContent with upstream @langchain/anthropic's handling, without
disturbing the fork's Vertex/GCP/Azure-specific corrections:
- restore an emptied tool_use input from the matching message.tool_calls args
- drop orphaned input_json_delta blocks and the v1-cast `text`-with-`input`
variant instead of throwing
Add a regression test for the aggregated-streaming tool-input scenario.
…ges them
Root-cause fix for the core >= 1.1.46 aggregation change. _makeMessageChunkFromAnthropicEvent
emitted the input_json_delta as a separate content block typed `input_json_delta`;
core now keeps differently-typed blocks separate, leaving the sibling tool_use
block's input empty and the delta orphaned. Every consumer that reads tool input
from message.content then breaks — re-serialization (_formatContent) and, e.g.,
@langchain/anthropic's AnthropicToolsOutputParser used by withStructuredOutput
(title generation), which threw OUTPUT_PARSING_FAILURE on empty input.
Emit the partial input as an untyped `{ index, input }` block so core merges it
into whichever block (tool_use or server_tool_use) sits at that index, restoring
the assembled input in message.content. Fixes all content-reading consumers at
the source; the message_inputs defensive handling stays as a safety net.
Add a unit test covering chunk emission + aggregation.
…am tool tests _formatContent now restores an emptied tool_use input from sibling input_json_delta blocks (by index) when there is no matching message.tool_calls entry — aligning with @langchain/anthropic and covering persisted messages that predate the chunk-emission fix. Port two upstream @langchain/anthropic regression tests that guard this path: - "partial tool input is correctly merged before calling Anthropic API" (unit) - "converting messages doesn't drop tool input" (live), adapted to CustomAnthropic
danny-avila
added a commit
to danny-avila/LibreChat
that referenced
this pull request
Jun 9, 2026
) * 🧰 fix: Flatten union schemas for Gemini/Vertex MCP tool compatibility `@langchain/google-common`'s `zod_to_gemini_parameters` throws "Gemini cannot handle union types" on any genuine `anyOf`/`oneOf` (e.g. discriminated unions), so MCP tools shipping union-typed schemas crash on the Google endpoint while working fine on OpenAI/Claude. Add `flattenJsonSchemaUnions` (packages/api) to collapse unions to their first non-null member and multi-entry `type` arrays to a single nullable type, and apply it in `createToolInstance`'s existing `isGoogle` branch so only the Google/Vertex path is affected. Lossy by design, mirroring the existing empty-object fallback. Closes #13612 * 🩹 fix: Address Codex review — preserve fields, strip null enums, cover definitions path - Preserve parent-level `properties`/`required` when collapsing a union: merge the chosen branch into the parent instead of overwriting, so args declared outside the union (e.g. always-required fields) still reach Gemini. - Drop the `null` member from `enum` when a union/type-array makes a field nullable, keeping Gemini's required homogeneous-enum invariant. - Propagate the Google-flattened schema to the definitions/deferred-tool path: thread `provider` into `loadToolDefinitions` and flatten there, and store the flattened schema on `mcpJsonSchema` so `extractMCPToolDefinition` no longer emits raw unions on Google/Vertex. * 🎨 style: Sort imports in tools/definitions per import-order check * ♊ feat: Broaden union flatten into a full Gemini schema sanitizer The union flatten alone wasn't enough — real GitHub MCP tools on Gemini also 400 with `Invalid value ... (TYPE_STRING), true`, because Gemini's function-calling Schema (https://ai.google.dev/api/caching#Schema) accepts only a restricted JSON Schema subset, and `enum` is `Type.STRING`-only. Rename `flattenJsonSchemaUnions` → `sanitizeGeminiSchema` and broaden it (one pass, Gemini-gated) to cover the documented subset: - Keep only string `enum` values; drop the keyword for non-string types (fixes the reported boolean-enum 400, incl. boolean `const` normalized to `enum: [true]`). - `const` → single-value string enum, or drop if non-string. - Merge `allOf` intersections; fold `exclusiveMinimum`/`exclusiveMaximum` into `minimum`/`maximum`. - Strip unsupported keywords: `additionalProperties`, `default`, `$schema`, `$id`. - (Existing) collapse `anyOf`/`oneOf`, multi-entry `type` arrays, nullable. Grounded in Google's Schema docs rather than reverse-engineered from 400s. Verified end-to-end against the real `@langchain/google-common` converter. Complements danny-avila/agents#232 (langchain bump), which defers schema flattening to LibreChat. * 🩹 fix: Gate enum retention on the effective (collapsed) type Codex review: a mixed-type enum like `type: ['integer','string'], enum: [1,'auto']` collapsed the type to `integer` but still kept the string value `'auto'`, yielding `{type:'integer', enum:['auto']}` — a non-string type with an enum, which Gemini rejects. Keep `enum` only when the effective collapsed type is string (or unset), and stamp `type: 'string'` on a surviving typeless enum (e.g. a string `const` discriminator) so it satisfies Gemini's Type.STRING enum requirement.
@langchain/core to 1.1.48 and @langchain/google-* to 2.1.31
@langchain/core to 1.1.48 and @langchain/google-* to 2.1.31@langchain/core 1.1.48 + google-* 2.1.31, with Anthropic tool-input compat fix
@langchain/core 1.1.48 + google-* 2.1.31, with Anthropic tool-input compat fix@langchain/core 1.1.48 + @langchain/google-* 2.1.31, with Anthropic tool-input compat fix
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Bumps the Google/LangChain stack to the latest patch releases and includes the Anthropic compatibility fix required to keep tool calling working under the new
@langchain/core:@langchain/core1.1.44→1.1.48@langchain/google-common/google-gauth/google-genai/google-vertexai2.1.28→2.1.31@anthropic-ai/sandbox-runtime→0.0.54(npm audit alignment)@langchain/core≥ 1.1.46 (see below)The
overrides$-references follow thedependenciesversions automatically. Lockfile regenerated.Anthropic tool-input compatibility fix
@langchain/core≥ 1.1.46 changed streaming content-block aggregation ("keep different block types separate when merging chunks" + "v1 message casting"). For Anthropic tool calls this now leaves thetool_usecontent block'sinputempty — the streamed input is split into a separateinput_json_deltablock (v1-cast to a straytextblock). The assembled arguments still live onmessage.tool_calls, but every consumer that reads tool input frommessage.contentbreaks:_formatContentre-serialization →Unsupported message content format(multi-turn tool calls, summarization).@langchain/anthropic'sAnthropicToolsOutputParser, used bywithStructuredOutput(e.g. title generation) →OUTPUT_PARSING_FAILUREon empty input.Fixed in two layers, without disturbing the fork's Vertex/GCP/Azure-specific handling:
utils/message_outputs.ts: emit the partial tool input as an untyped{ index, input }block so core merges it back into whichever block sits at that index (tool_useorserver_tool_use), restoring the input inmessage.content. Fixes all content-reading consumers at the source.utils/message_inputs.ts_formatContent: restore an emptiedtool_useinput frommessage.tool_calls, falling back to merging siblinginput_json_deltablocks by index; drop orphaned delta /text-with-inputblocks instead of throwing. Covers persisted/legacy messages.Tests
utils/streaming-tool-input.test.ts): orphan-skip, restore-from-tool_calls, no-overwrite, sibling-delta merge, and type-less chunk emission + aggregation.llm.spec.ts): "converting messages doesn't drop tool input".@langchain/anthropic's own regression suite.Why core and google-* must move together
@langchain/google-common@2.1.29(PR #10776) switched function-call id generation back to importingv4from@langchain/core/utils/uuid(2.1.28 imported it from standaloneuuid). That import path is what crashed in LibreChat#13003 —(0, _langchain_core_utils_uuid.v4) is not a function— due to a Rolldown CJS emit bug in older@langchain/core.@langchain/core@1.1.48(PR #10832, "make CJS default re-exports callable") fixes that emit. Verified:So the revert is safe only when core is also ≥ 1.1.48. Note
google-common@2.1.31only declarescore ^1.1.47, but the callable-export fix landed in 1.1.48 — so core is pinned to an exact1.1.48here, not a^range.Changelog breakdown (current → bumped)
@langchain/core1.1.44 → 1.1.48 — 1.1.45 deprecations + Deno fix · 1.1.46 inlineansi-styles/camelcase/decamelize, keep distinct content-block types separate when merging · 1.1.47 add UUIDv6, v1 casting after streaming aggregation · 1.1.48fix(core): make CJS default re-exports callable(#10832; the #13003 root cause), OpenRouter reasoning v1 blocks, OpenAI Responses custom-tool streaming.@langchain/google-common2.1.28 → 2.1.31 — 2.1.29 uuid-vuln remediation (reverts to core uuid import, #10776) · 2.1.30 structured output parsing withincludeRaw+reasoning · 2.1.31fix: missing stream usage metadata on Gemini(#9912).google-genai/google-gauth/google-vertexai— uuid remediation (genai) + dependency passthroughs.What this does NOT do
Does not address the Gemini union-type schema throw (
zod_to_gemini_parameters: Gemini cannot handle union types, langchainjs#9691) — still open upstream and unchanged ingoogle-common@2.1.31. That case is handled downstream in LibreChat by flattening union schemas before they reach the Gemini converter.Validation
npm installclean (no peer-dependency conflicts);npm run build(rollup +tsc) clean.